﻿using System;
using System.Collections.Generic;
using Assets.Script.NetSystem.Battle.Core;
using LiteNetLib;
using LiteNetLib.Utils;
using Newtonsoft.Json;
using SimpleTools.Json;
using SimpleTools.Net.SimpleServer.UDP;
using UnityEngine;
using static SimpleTools.Net.SimpleServer.UDP.GetInterfaces;

namespace Script.NetSystem.Core
{

    public delegate void ConnectSuccess();
    public delegate void PollHandler();
    
    /// <summary>
    /// 规定 接口处理方法名为"Hanlder"
    /// 接口参数为(T,JsonData)
    /// JsonData内分发动作关键词key为action
    /// </summary>
    /// <typeparam name="TManager"></typeparam>
    public class SimpleCilent<TManager>
    {
        public ConnectionState ConnectionState { get { return socketCore.peer.ConnectionState; } }

        protected Dictionary<string, InterfaceClass> distribute = new Dictionary<string, InterfaceClass>();

        private ConnectSuccess finished;
        private SocketCore socketCore = new SocketCore();

        TManager manager;
        EventBasedNetListener netListener;
        
        public SimpleCilent(Type HandlerInterface,TManager manager, EventBasedNetListener netListener, ConnectSuccess finished, Type[] actionTypes,bool isJson = true ,Dictionary<string, InterfaceClass> distribute_=null)
        {
            distribute = GetInterfaces.GetIs(HandlerInterface, "Handler", actionTypes);
            if (distribute_!=null)
            {
                foreach (var item in distribute_.Keys)
                {
                    distribute.Add(item, distribute_[item]);
                }
            }

            this.manager = manager;
            this.netListener = netListener;
            this.finished = finished;
            if (isJson)
            {
                netListener.NetworkReceiveEvent += OnNetworkReceive_Json;
            }
            else
            {
                netListener.NetworkReceiveEvent += OnNetworkReceive;
            }
            
        }


        public void Start(string ip, int port, string key="???")
        {
            socketCore.Start(ip, port, key, netListener);
        }
        
        public void Start(string ip, int port, NetDataWriter writer)
        {
            socketCore.Start(ip, port, writer, netListener);
        }

        /// <summary>
        /// 消息处理，每次调用才回处理网络消息
        /// </summary>
        public void Poll()
        {
            socketCore.Poll();
        }

        public void Stop()
        {
            socketCore.Stop();
        }

        /// <summary>
        /// 发送信息：用于带json的
        /// </summary>
        /// <param name="data"></param>
        public void Send(JsonData data)
        {
            socketCore.peer.Send(NetDataWriter.FromString(data.Json), DeliveryMethod.ReliableOrdered);
        }
        /// <summary>
        /// 发送消息：不带json的（基本数据类型）
        /// </summary>
        /// <param name="writer"></param>
        public void Send(NetDataWriter writer)
        {
            socketCore.peer.Send(writer, DeliveryMethod.ReliableOrdered);
        }
        private void OnNetworkReceive_Json(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod)
        {
            try
            {
                string s = reader.GetString();
                var json = JsonConvert.DeserializeObject<JsonData>(s);
            
                InterfaceClass interfaceClass;
                distribute.TryGetValue(json.GetStr("action"), out interfaceClass);
              
                if(interfaceClass!=null)
                {
                    
                    var objects = new object[]{manager, json};
                    interfaceClass.Invoke(ref objects);
                }
                else
                {
                    if (json.GetStr("action") == "connsuc")
                    {
                        finished.Invoke();
                    }
                    else
                    {
                        Debug.LogError("Handler can not find " + json.GetStr("action"));
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
            
            reader.Recycle();
        }
        
        private void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod)
        {
            try
            {
                int len = reader.GetInt();
                string key = reader.GetString(len);

                InterfaceClass interfaceClass;
                distribute.TryGetValue(key, out interfaceClass);

                if (interfaceClass != null)
                {

                    var objects = new object[] { manager, reader };
                    interfaceClass.Invoke(ref objects);
                }
                else
                {
                    if (key == "connsuc")
                    {
                        finished.Invoke();
                    }
                    else
                    {
                        Debug.LogError("Handler can not find " + key);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

            reader.Recycle();
        }
    }
}

